#ifndef CFDL_PTL_TYPE_H
#define CFDL_PTL_TYPE_H

#include <stdint.h>
#include <functional>

#define CFDL_BASEVERSION    1                     //消息包结构版本 0对应v0.8以前cfdl通讯
#define CFDL_VERSION_M      1                     //协议主版本号，向下不一定兼容
#define CFDL_VERSION_S      7                     //协议小版本号，保证向下兼容

#define CFDL_VID      0x01                 //本模块的VID
#define CFDL_PID      0x001C               //本模块的PID
#define CFDL_CHID     0x001                //本模块的通道ID，启用的情况下将关闭自动通道协商
#define CFDL_MSG_LEN  (2048)               //消息Payload长度,包总长度 = 17 + CFDL_MSG_LEN,建议等于CFDL_EMA_SIZE/3左右

#define CF_ISSELF(id) ((id.vid==CFDL_VID)&&(id.pid==CFDL_PID)&&(id.chid==CFDL_CHID))

#pragma pack (1)
//标准设备ID结构
typedef struct
{
    uint8_t chid;
    uint8_t vid;
    uint16_t pid;
}CFID;

//标准协议包
typedef struct
{
    uint8_t start;//0x55
    uint8_t type;//帧类型 -- 必须项
    uint16_t len;//长度 -- 必须项
    uint16_t seq;//消息id
    CFID src;//源ID
    CFID dst;//目标ID -- 必须项
    uint16_t msid;//消息id -- 必须项
    uint8_t *payload; //  -- 必须项
    uint8_t check;//校验和
}cfdl_message_t;

typedef struct
{
    uint8_t    State;//系统当前状态
    uint16_t   Ability;//信道能力
    uint8_t    Deep;//信道深度
    uint8_t    MVersion;//主版本号
    uint8_t    SVersion;//小版本号
    uint32_t   RunTime;//当前运行时间
    uint16_t   QPS;//当前系统吞吐量
    uint8_t    HBTime;//当前系统心跳时间
}cfdl_heartbeat_t;

#pragma pack ()

//解包联合体
typedef union
{
    cfdl_message_t msg;
    uint8_t cfdl_data[sizeof(cfdl_message_t)];
}cfdl_decode_msg_t;//用于解包的联合体

//通讯的IO节点
typedef struct
{
    uint8_t en;//使能标记
    std::function<void (int, uint8_t*)> data_out;//数据输出回调 输出通道号
    uint8_t read_state;//读数据状态
    uint8_t check;//校验运算
    uint16_t payload_r;//当前接收的消息内容长度
    cfdl_decode_msg_t read_temp;//读数据缓存
}cfdl_io_node_t;

typedef std::function<void (cfdl_message_t*)> cfdl_msg_fun_cb;

typedef struct
{
    uint16_t msgid;
    cfdl_msg_fun_cb cb_fun;//msg 消息回调接口
    cfdl_msg_fun_cb ack_e; //ack 错误回调接口
}cmd_module_node;

//帧类型
typedef enum
{
    FRAME_REQ_TYPE=0,//请求帧
    FRAME_ACK_TYPE,//应答帧
    FRAME_DAT_TYPE,//数据帧
    FRAME_RESI_TYPE,//残帧
}CFDL_FRAME_TYPE;
//标准应答码
typedef enum
{
    ACK_SUCCESS=0,           //标记命令执行成功
    ACK_FAIL,                //标记命令执行失败
    ACK_HARDWARE_ERROR,      //硬件忙或者硬件未就绪
    ACK_NO_COMMAND,          //命令本模块不支持
    ACK_ARG_ERROR,           //命令参数解析错误或参数越界
    ACK_SYSTEM_ERROR,        //系统处于异常工作状态中
    ACK_NO_SD,               //当前系统无SD卡
    ACK_SD_FULL,             //当前系统SD卡满了
    ACK_SD_INCOMPATIBLE,     //当前系统SD卡不兼容
    ACK_SD_WRITE,            //当前系统SD卡写错误
    ACK_SD_READ,             //当前系统SD卡读错误
    ACK_SD_OP_FILE,          //当前系统SD卡操作失败
    ACK_SD_FORMAT,           //当前系统SD卡格式化失败
    ACK_SD_FILESYSTEM,       //当前系统SD卡文件系统错误
    ACK_SD_FRAME,            //当前系统SD卡簇大小错误
    ACK_FILE_CUT_BIG,        //文件切片太大
    ACK_FILE_OPEN,           //无法打开文件
    ACK_FILE_REOPEN,         //主机文件系统占线
    ACK_FILE_DATA,           //文件未打开
    ACK_FILE_READ,           //文件读取失败
    ACK_TIME_OUT,            //操作超时
    ACK_SN_RWRITE,           //SN重复写入
}CFDL_ACK;

enum CFDL_ERR
{
    CFDL_UNKNOW_E=0,//未知错误
    CFDL_RLEN_E,//接收消息过长错误 消息id
    CFDL_WLEN_E,//发送消息过长错误 消息id
    CFDL_CHECK_E,//检验和失败错误 消息id
    CFDL_DEVICE_E,//设备错误
    CFDL_ACK_E,//应答超时
    CFDL_ACK_LIST_E,//ACK表溢出
    CFDL_IO_ADD_E,//添加IO节点错误
    CFDL_RO_FIFO_E,//路由FIFO溢出
    CFDL_RO_ROLIST_E,//路由表溢出
    CFDL_EMA_OUT_OF_MEMORY,//内存空间不足
    CFDL_EMA_OUT_OF_INFO,//内存描述空间不足
    CFDL_EMA_NO_FREE_MEMORY,//没有足够自由空间
    CFDL_EMA_NO_FIND_ADDRESS,//没有找到地址
    CFDL_EMA_MALLOC_ERR,//内存地址分配有误
};

#endif // CFDL_PTL_TYPE_H
